<!DOCTYPE html>
<html>
	<head>
		<title>canvas-时钟</title>
	</head>
	<style>
		body {
			margin: 0;
			padding: 0;
			box-sizing: border-box;
			height: 100vh;
			display: flex;
			align-items: center;
			justify-content: center;
			background: #222;
		}
	</style>
	<body>
		<canvas id="mycanvas">该浏览器不支持canvas</canvas>
	</body>
	<script>
		var canvas = document.getElementById("mycanvas");
		var ctx = canvas.getContext("2d");
		var WIDTH = document.documentElement.clientWidth / 2;
		var HEIGHT = document.documentElement.clientHeight / 2;
		canvas.width = WIDTH;
		canvas.height = HEIGHT;
		var center = [WIDTH / 2, HEIGHT / 2]; // 表盘中心坐标
		// 表盘半径
		if (WIDTH > HEIGHT)
			var radius = HEIGHT / 2 - 50;
		else
			var radius = WIDTH / 2 - 50;
		// 根据当前时间，求出三根针的角度
		function calcDegree() {
			var myDate = new Date();
			var myTime = myDate.toLocaleTimeString().substring(2, myDate.length); //获取当前时间
			var t1 = myTime.split(":");
			t1[0] = Number(t1[0]);
			t1[1] = Number(t1[1]);
			t1[2] = Number(t1[2]);
			var hourDegree = t1[0] % 12 * 30 + 30 * (t1[1] * 60 + t1[2]) / 3600;
			var minDegree = t1[1] / 60 * 360 + 6 * t1[2] / 60;
			var secDegree = t1[2] / 60 * 360;
			return {
				hourDegree: hourDegree,
				minDegree: minDegree,
				secDegree: secDegree
			}
		}
		// 画线的函数，（粗细、颜色、起点、角度、长度）
		function drawLine(lineWidth, color, startDot, deg, lineLen) {
			ctx.lineWidth = lineWidth;
			ctx.beginPath();
			ctx.moveTo(startDot[0], startDot[1]);
			ctx.lineTo(startDot[0] + lineLen * Math.sin(deg * Math.PI / 180), startDot[1] - lineLen * Math.cos(deg * Math
				.PI / 180));
			ctx.closePath();
			ctx.strokeStyle = color;
			ctx.stroke();
		}

		// 画表盘上不动的地方，就是除了指针以外的部分
		function drawPan() {
			// 画圆
			ctx.beginPath();
			ctx.lineWidth = 5;
			ctx.strokeStyle = "orange";
			ctx.arc(center[0], center[1], radius, 0, 2 * Math.PI);
			// 画数字
			ctx.font = radius * 0.12 + "px 方正舒体"; // 设置字体、大小，随半径变化
			ctx.textAlign = "center"; // 设置水平对齐
			ctx.textBaseLine = "Bottom"; //设置垂直对齐
			for (i = 1; i <= 12; i++) {
				var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
				gradient.addColorStop("0", "orange");
				gradient.addColorStop("0.5", "pink");
				gradient.addColorStop("1.0", "red");
				// 用渐变填色
				ctx.fillStyle = gradient;
				// 获取数字的位置
				var deg = i % 12 * 30;
				var numLen = radius * 0.9; //数字所在的半径
				var x = center[0] + numLen * Math.sin(deg * Math.PI / 180);
				var y = center[1] - numLen * Math.cos(deg * Math.PI / 180);
				ctx.fillText(i, x, y);
			}
			ctx.stroke();
		}

		// 写一个函数，根据当前时间画钟
		function draw() {
			ctx.clearRect(0, 0, WIDTH, HEIGHT); //清空画布，否则有重影
			// 画周围的刻度和表盘
			drawPan();
			// 获取当前时间的角度
			t2 = calcDegree();
			drawLine(7, 'orange', center, t2.hourDegree, radius * 0.4); //画时针
			drawLine(5, 'pink', center, t2.minDegree, radius * 0.6); //画分针
			drawLine(3, 'skyblue', center, t2.secDegree, radius * 0.7); //画秒针
			requestAnimationFrame(draw);
		}
		draw();
		// requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点：
		// 1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来，在一次重绘或回流中就完成，并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率，一般来说，这个频率为每秒60帧。
		// 2、在隐藏或不可见的元素中，requestAnimationFrame将不会进行重绘或回流，这当然就意味着更少的的cpu，gpu和内存使用量。
		// 取消:cancelAnimationFrame()接收一个参数,requestAnimationFrame默认返回一个id，cancelAnimationFrame只需要传入这个id就可以停止了。
	</script>
</html>
